#pragma once
#include "Header.h"

namespace IO
{
	class _declspec(dllexport) IO
	{
	private:
		unsigned int position;
		std::fstream Stream;
		long size;
	public:
		IO(){ };
		~IO(){ };
		template <typename T>
		IO& operator << (T& ret)
		{
			Read<T>(ret);
			return *this;
		}
		template <typename T>
		IO& operator >> (T& ret)
		{
			Write<T>(ret);
			return *this;
		}

		bool B_StreamIN(const std::string& Filename);	//Binary File-In-Stream
		bool B_StreamOUT(const std::string& Filename);	//Binary File-Out-Stream
		bool N_StreamOUT(const std::string& Filename); //Normal File-Out-Stream
		void Close(){ Stream.close(); }

		template <typename T>
		T Read(T& ret)
		{
			  Stream.read(reinterpret_cast<char*>(&ret), sizeof(T));
			  return ret;
		}

		template <typename T>
		T ReadAt(T& ret, unsigned int Offset)
		{
			position = Offset;
			Stream.seekg(position, std::ios::beg);
			Stream.read(reinterpret_cast<char*>(&ret), sizeof(T));
			position += sizeof(T);
			return ret;
		}

		template <typename T>
		T ReadAtTo(T& ret, unsigned int Start, unsigned int End)
		{
			Stream.seekg(Start, std::ios::beg);
			unsigned int d_size = End - Start;
			Stream.read(reinterpret_cast<char*>(&ret), d_size);
			position += d_size;
			return ret;
		}

		template <typename T>
		void Write(T& ret)
		{
			Stream.write(reinterpret_cast<char*>(&ret), sizeof(T));
		}
		void Write(int& ret);

		template <typename T>
		T ReadChunk(T& ret)
		{
			unsigned int size;
			Stream.seekg(position+4, std::ios::beg);
			Stream.read(reinterpret_cast<char*>(size), 4);
			Stream.seekg(position-8, std::ios::beg);
			Stream.read(reinterpret_cast<char*>(&ret), size);
			return ret;
		}

		void Write(std::string text);
		void Write(std::string& time, std::string text);

		void SetOffset(unsigned int Offset)
		{ 
			position = Offset; 
			Stream.seekg(position, std::ios::beg);
		}
		unsigned int GetOffset(){ return position; }
		unsigned long GetSize(){ return size; }
		unsigned int SearchChunk(const std::string& ChunkName);
	};
}